RedisTemplate 使用 Redis zset 实现排行榜(日榜、总榜)

您所在的位置:网站首页 redis zset并集 RedisTemplate 使用 Redis zset 实现排行榜(日榜、总榜)

RedisTemplate 使用 Redis zset 实现排行榜(日榜、总榜)

2023-06-04 01:03| 来源: 网络整理| 查看: 265

需求

1、比赛记录分数,统计日榜和总榜

2、排行榜保留前3名

实现 一、引入redis org.springframework.boot spring-boot-starter-data-redis 复制代码 二、配置yml spring: redis: host: localhost port: 6379 复制代码 三、初始化RedisTemplate @Configuration public class RedisConfig { @Bean public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){ RedisTemplate redisTemplate = new RedisTemplate(); //连接工厂 redisTemplate.setConnectionFactory(redisConnectionFactory); //设置序列化器 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class)); return redisTemplate; } } 复制代码 四、创建redis工具类 @Component public class RedisUtils { @Resource private RedisTemplate redisTemplate; // 相关方法会在后面说明 .... } 复制代码 五、编写业务逻辑 1、每日新增排名

每日排名用日期作为key分割开

@Test void addDayData() { // 添加第一天数据 String key1 = "score:rank:20220620"; redisUtils.zAdd(key1, "jack", 100); redisUtils.zAdd(key1, "david", 150); redisUtils.zAdd(key1, "chris", 76); redisUtils.zAdd(key1, "soho", 200); // 添加第二天数据,其中david两天都有参赛,并且第二天成绩比第一天好 String key2 = "score:rank:20220621"; redisUtils.zAdd(key2, "justin", 30); redisUtils.zAdd(key2, "david", 173); redisUtils.zAdd(key2, "luke", 89); redisUtils.zAdd(key2, "gk", 190); } 复制代码

redisUtils.zAdd()方法的实现如下:

/** * 向zset中添加分数 * @param key key * @param value 存放唯一标识 * @param score 分数 * @return boolean */ public Boolean zAdd(String key, String value, double score) { return redisTemplate.opsForZSet().add(key, value, score); } 复制代码 2、获取日榜前三数据 @Test void getDayRank() { // 获取日榜前三,假如今天是20220621 String key = "score:rank:20220621"; redisUtils.zReverseRangeWithScores(key, 0, 2) .forEach(item -> System.out.printf("user: %s, score: %s%n", item.getValue(), item.getScore())); } 复制代码

redisUtils.zReverseRangeWithScores()方法的实现如下:

/** * 从大到小截取数据 * @param key key * @param start 从哪里开始(0表示第一名) * @param end 截取到哪(9表示截取10名) * @return Set */ public Set zReverseRangeWithScores(String key, long start, long end) { return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end); } 复制代码

2022年6月21日的排名如下:

user: gk, score: 190.0 user: david, score: 173.0 user: luke, score: 89.0 复制代码 3、获取总榜前三数据 @Test void getTotalRank() { // 获取所有日榜的keys Set listKey = redisUtils.getListKey("score:rank"); String key = "score:rank:20220621"; String destKey = "score:rank:total"; // 先查缓存 Set typedTuples = redisUtils.zReverseRangeWithScores(destKey, 0, 2); if (typedTuples.isEmpty()) { // 没有缓存的话将日榜并集,并将结果存储到新key,并设置有效期为15分钟 redisUtils.zUnionAndStore(key, listKey, destKey); redisUtils.expire(destKey, 15L, TimeUnit.MINUTES); typedTuples = redisUtils.zReverseRangeWithScores(destKey, 0, 2); } // 获取总榜前10 typedTuples.forEach(item -> System.out.printf("user: %s, score: %s%n", item.getValue(), item.getScore())); } 复制代码

2022年6月21日的总排名如下:

user: soho, score: 200.0 user: gk, score: 190.0 user: david, score: 173.0 复制代码

redisUtils.zUnionAndStore() 和 redisUtils.expire() 的实现如下:

/** * 并集所有keys * * RedisZSetCommands.Aggregate.MAX -> 保留最大 * RedisZSetCommands.Aggregate.MIN -> 保留最小 * RedisZSetCommands.Aggregate.SUM -> 相加(默认) * * @param key 要被并集的key * @param otherKeys 所有要并集的key * @param destKey 新key * @return 新set的长度 */ public Long zUnionAndStore(String key, Collection otherKeys, String destKey) { return redisTemplate.opsForZSet().unionAndStore(key, otherKeys, destKey, RedisZSetCommands.Aggregate.MAX); } /** * 设置key的过期时间 * @param key 目标key * @param timeout 时间 * @param timeUnit 单位 * @return boolean */ public Boolean expire(String key, long timeout, TimeUnit timeUnit) { return redisTemplate.expire(key, timeout, timeUnit); } 复制代码 参考

【开发经验】redis排行榜功能(日榜、周榜、月榜)

Redis工具类RedisUtils



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3